package com.easybuilder.blog.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.easybuilder.blog.dao.BlogLikesDao;
import com.easybuilder.blog.entity.BlogLikes;
import com.easybuilder.blog.service.LikesService;
import com.easybuilder.common.utils.UserUtil;
import com.easybuilder.core.rbac.entity.SysUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

@Slf4j
@Service
public class LikesServiceImpl implements LikesService {

    @Resource
    private BlogLikesDao likesDao;

    /**
     * @Author zhangxingshuai
     * @Description 点赞或回踩
     * @Date 11:19 2022/1/26
     * @Param  点赞实体类
     * @return 返回最新点赞、反对数量
     **/
    @Override
    public Map<String, Integer> like(BlogLikes blogLikes) {
        // 查询当前用户对该作品的点赞数据
        BlogLikes likesRecord = getLikesRecord(blogLikes);
        // 如果当前不存在点赞数据，直接新建一条点赞记录，此处需要做并发处理，防止同一用户，在不同设备下同时点赞
        if (likesRecord == null) {
            ReentrantLock lock = new ReentrantLock();
            try {
                lock.tryLock(3, TimeUnit.SECONDS);
                likesRecord = getLikesRecord(blogLikes);
                // 如果双重判空后，点赞记录还是为空，说明当前用户没有点赞记录
                if (likesRecord == null) {
                    blogLikes.setCreateTime(new Date());
                    int insert = likesDao.insertSelective(blogLikes);
                    log.info("插入点赞记录：{}", insert);
                } else { // 如果双重判空出现点赞记录，说明存在并发操作，导致已经点赞成功，此处不做处理
                    log.info("双重判空，已点赞");
                }
                lock.unlock();
                log.info("点赞完成，释放锁");
            } catch (Exception exception) {
                exception.printStackTrace();
            }
        } else {
            Integer status = likesRecord.getStatus();
            // 如果当前点赞状态与实际存储记录不一致，做更新操作
            if (status.intValue() != blogLikes.getStatus().intValue()) {
                // 更新点赞状态
                likesRecord.setStatus(blogLikes.getStatus());
                likesRecord.setUpdateTime(new Date());
                likesDao.updateByPrimaryKeySelective(likesRecord);
            }
        }
        // 获取并返回当前作品的点赞/回踩的最新数据量
        return likesDao.sumLikes(blogLikes.getArticleId(), blogLikes.getType());
    }

    @Override
    public List<BlogLikes> selectByExample(Example example) {
        return likesDao.selectByExample(example);
    }

    @Override
    public List<JSONObject> batchSumLikes(Integer type, String articleIds){
        return likesDao.batchSumLikes(type, articleIds);
    }

    /** 获取当前用户的点赞记录 */
    private BlogLikes getLikesRecord(BlogLikes blogLikes) {
        //TODO 后续userId需要通过后端获取（可以放到认证信息中），不要通过前端直接传递
        SysUser user = UserUtil.getUser();
        log.info("本地存储获取当前用户信息：{}", JSONObject.toJSONString(user));
        if (user != null) {
            Long id = user.getId();
            blogLikes.setUserId(id);
        }
        Example example = new Example(BlogLikes.class);
        example.createCriteria().andEqualTo("articleId",blogLikes.getArticleId()).andEqualTo("userId", blogLikes.getUserId())
                .andEqualTo("type", blogLikes.getType());
        BlogLikes likesRecord = likesDao.selectOneByExample(example);
        return likesRecord;
    }
}
